﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Collections.Specialized;
using System.Windows.Threading;
using System.Threading;
using FinPlusUtility;
using FinPlusDBConn;
using FinPlusCommon;
using u = FinPlusUtility.Utility;
using log = Logger.Logger;

namespace FinPlusWPFControls
{
    public partial class FinPlusFuncEditor : FinPlusControl
    {
        public override string Id { get; set; }
        public override string[] States { get { return new string[] { "ColumnState" }; } }
        public override string[] TestStates { get { return new string[] { "IsValid", "ModelTest", "ColumnState" }; } }
        public override IFinPlusFunctions Model { get { return _model; } }
        public override string ModelTest { get { return _model.ToString(); } }
        public override bool IsValid { get; set; }

        public string ColumnState { get { return _colHelper.GetColState(dataGrid); } set { _colHelper.SetColState(dataGrid, _colSelectBar, value); } }

        private enum Params { Tag }
        private enum Cols { Id, Name, Value, TimeStamp, User, Type }
        private CollectionViewSource _viewSource;
        private IFinPlusDBConn _conn;
        private readonly SynchronizationContext _context;
        private readonly FinPlusColSelectBar _colSelectBar;
        private readonly FinPlusColHelper _colHelper;
        private readonly IFinPlusFunctions _model;
        private IFinPlusFunction _copy, _func;
        private Action<string> _title;

        //construct
        public FinPlusFuncEditor(IFinPlusDBConn conn)
        {
            InitializeComponent();

            _model = new Functions();
            _conn = conn;
            _colSelectBar = new FinPlusColSelectBar();
            _colSelectBar.ColSelection += ColSelector_OnSelection;
            _colHelper = new FinPlusColHelper(null, null, null, string.Empty, string.Empty, string.Empty, string.Empty);
            _context = SynchronizationContext.Current;
            colSelectotGrid.Children.Add(_colSelectBar);

            Initialise();
        }

        //common control interface
        public override void Dock(object control, string dock)  
        { 
        
        }

        public override void Initialise()
        {
            foreach (string name in Enum.GetNames(typeof(Cols)))
                _colSelectBar.AddButton(name, false);

            foreach (var col in dataGrid.Columns)
                col.SetValue(TagProperty, col.Header);

            statusBar.Children.Add(new FinPlusStatusBar());
        }

        public override void CommandRouter(IFinPlusFunction func)
        {
            try
            {
                CaptureCommand(func);

                switch ((Commands)Enum.Parse(typeof(Commands), func.Name, true))
                {
                    case Commands.Save: Save(); break;
                    case Commands.Close: Close(); break;
                    case Commands.Change: Change(func[Params.Tag.ToString()].ToString()); break;
                    case Commands.Undo: Undo(); break;
                    case Commands.Loaded: Refresh(); break;
                    case Commands.ColSelection: AddColSelection(func[Params.Tag.ToString()].ToString()); break;
                    default: throw new Exception(string.Format("event not recognised {0}", func.Name));
                }
            }
            catch (Exception e)
            {
                IsValid = log.Log(Logger.Level.Warning, e.Message, e);
            }
        }

        public override void Dispose() { }

        //public
        public void Set(IFinPlusFunction func, Action<string> title = null)
        {
            //GetPermission()//TODO
            _func = func;
            _func.ItemUpdate += (s, a) => this.Dispatcher.Invoke(() => Item_Update(s, a));

            if(title != null) _title = title;

            _copy = _func.Clone(_func.Id);
            _viewSource = new CollectionViewSource() { Source = _func };
            _viewSource.SortDescriptions.Clear();
            _viewSource.SortDescriptions.Add(new SortDescription("Index", ListSortDirection.Ascending));
            
            dataGrid.ItemsSource = _viewSource.View;
            IsValid = true;

            SetBooker();
        }

        //private
        private void AddSelectBox(DataGridCell cell, IList<string> list)
        {
            var tb = new FrameworkElementFactory(typeof(FinPlusValueSelectBox));
            tb.SetValue(FinPlusValueSelectBox.IdProperty, _func.Id.ToString());
            tb.SetValue(FinPlusValueSelectBox.FunctionNameProperty, _func.Name);
            tb.SetValue(FinPlusValueSelectBox.IsEnabledProperty, true);
            tb.SetValue(FinPlusValueSelectBox.ItemSourceProperty, list);
            tb.SetBinding(FinPlusValueSelectBox.TextProperty, new Binding("Value") { Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });

            var dt = new ControlTemplate() { VisualTree = tb };
            cell.Template = dt;
        }

        private void AddColSelection(string name)
        {
            var col = dataGrid.Columns.Where(c => c.GetValue(TagProperty).ToString().Equals(name)).First();
            col.Visibility = col.Visibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
        }

        private void Save()
        {
            if (_conn == null) _conn = new FinPlusConn();
            _copy = _func.Clone(_func.Id);
            _conn.Save(_func);
            SetBooker();
            Refresh();
        }

        private void Undo()
        {
            _func = _copy.Clone(_copy.Id);
            Set(_func);
            Refresh();
        }

        private void Close()
        {
            var r = MessageBox.Show("Do you want to remove trade", "Confirmation", MessageBoxButton.YesNo, MessageBoxImage.Question);
            if (r != MessageBoxResult.Yes) return;
            if (_conn == null) _conn = new FinPlusConn();
            var res = _conn.Close(_func);
            SetBooker();
            Refresh();
        }

        private void Change(string index)
        {
            if (!_func[index].ToString().Equals(_copy))
                _func.Get(index).TimeStamp = DateTime.MinValue;
          
            SetBooker();
        }

        private void SetBooker()
        {
            if (_func == null)
            {
                _title("Unbooked");
                bSave.Visibility = Visibility.Visible;
                bClose.Visibility = bAmend.Visibility = Visibility.Collapsed;
            }
            else if (_func.Id < 0)//new trade
            {
                _title("Unbooked");
                bSave.Visibility = Visibility.Visible;
                bClose.Visibility = bAmend.Visibility = Visibility.Collapsed;
            }
            else if (_func.IsClosed)//closed trade
            {
                _title(string.Format("{0} (Id {1}) Removed", _func.Name, _func.Id.ToString()));
                dataGrid.IsEnabled = false;
                bUndo.Visibility = bSave.Visibility = bClose.Visibility = bAmend.Visibility = Visibility.Collapsed;
            }
            else //saved trade
            {
                _title(string.Format("{0} (Id {1})", _func.Name, _func.Id.ToString()));
                bSave.IsEnabled = false;
                bSave.Visibility = Visibility.Collapsed;
                bClose.Visibility = bAmend.Visibility = Visibility.Visible;
            }
            bUndo.Visibility = _func.IsEqual(_copy) ? Visibility.Collapsed : Visibility.Visible;
        }

        private void Refresh()
        {
            _viewSource.View.Refresh();
            for (int row = 0; row < dataGrid.Items.Count; row++)
            {
                var name = ((TextBlock)DataGridHelper.GetCell(dataGrid, row, 1).Content).Text;
                var cell = DataGridHelper.GetCell(dataGrid, row, 2);
                var list = Structure.ToList(name);

                if (Function.Protected.Contains(name))
                    cell.IsEnabled = false;
                else if (list.Count > 0)
                    AddSelectBox(cell, list);
            }
        }

        //cmds
        private new enum Commands { Save, Close, Undo, Change, Loaded, ColSelection }

        //events
        private void Close_OnClick(object sender, RoutedEventArgs a) { CommandRouter(new Function(Commands.Close.ToString(), Id, User)); }
        private void Save_OnClick(object sender, RoutedEventArgs a) { CommandRouter(new Function(Commands.Save.ToString(), Id, User)); }
        private void Undo_OnClick(object sender, RoutedEventArgs a) { CommandRouter(new Function(Commands.Undo.ToString(), Id, User)); }
        private void Item_Update(object sender, ItemEventArgs a) { CommandRouter(new Function(Commands.Change.ToString(), Id, User, -1, a.Item.Name)); }
        private void Grid_Loaded(object sender, RoutedEventArgs a) { CommandRouter(new Function(Commands.Loaded.ToString(), Id, User)); }
        private void ColSelector_OnSelection(object sender, IFinPlusFunction func) { CommandRouter(func); }
    }
}
